using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

public class RSAEncode :IEncode,IDecode
{
    private RSAParameters m_RSAParameters;
    
    public RSAEncode(RSAParameters rsaParameters)
    {
        m_RSAParameters = rsaParameters;
    }
    
    
    public static  byte[] RSAEncrypt(byte[] DataToEncrypt, RSAParameters RSAKeyInfo, bool DoOAEPPadding)
    {
        try
        {
            //Create a new instance of RSACryptoServiceProvider.
            RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();

            //Import the RSA Key information. This only needs
            //toinclude the public key information.
            RSA.ImportParameters(RSAKeyInfo);

            //Encrypt the passed byte array and specify OAEP padding.  
            //OAEP padding is only available on Microsoft Windows XP or
            //later.  
            return RSA.Encrypt(DataToEncrypt, DoOAEPPadding);
        }
        //Catch and display a CryptographicException  
        //to the console.
        catch (CryptographicException e)
        {
            GameDebug.LogError(e.Message+"\n"+e.StackTrace);

            return null;
        }

    }

    public static  byte[] RSADecrypt(byte[] DataToDecrypt, RSAParameters RSAKeyInfo, bool DoOAEPPadding)
    {
        try
        {
            //Create a new instance of RSACryptoServiceProvider.
            RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();

            //Import the RSA Key information. This needs
            //to include the private key information.
            RSA.ImportParameters(RSAKeyInfo);

            //Decrypt the passed byte array and specify OAEP padding.  
            //OAEP padding is only available on Microsoft Windows XP or
            //later.  
            return RSA.Decrypt(DataToDecrypt, DoOAEPPadding);
        }
        //Catch and display a CryptographicException  
        //to the console.
        catch (CryptographicException e)
        {
            Console.WriteLine(e.ToString());

            return null;
        }

    }

    
    //对数据签名
    public static byte[] HashAndSign(byte[] dataToSign, string str_Private_Key)
    {
        byte[] DataToSign = dataToSign;
        try
        {
            RSACryptoServiceProvider RSAalg = new RSACryptoServiceProvider();
            RSAalg.ImportCspBlob(Convert.FromBase64String(str_Private_Key));
            byte[] signedData = RSAalg.SignData(DataToSign, new SHA1CryptoServiceProvider());
            return signedData;
        }
        catch (CryptographicException e)
        {
            GameDebug.Log(e.Message);
            return null;
        }
    }

    //验证签名
    public static bool VerifySignedHash(byte[] DataToVerify, byte[] SignedData, string str_Public_Key)
    {
        try
        {
            RSACryptoServiceProvider RSAalg = new RSACryptoServiceProvider();
            RSAalg.ImportCspBlob(Convert.FromBase64String(str_Public_Key));
            
            return RSAalg.VerifyData(DataToVerify, new SHA1CryptoServiceProvider(), SignedData);

        }
        catch (CryptographicException e)
        {
            GameDebug.Log(e.Message);

            return false;
        }
    }
 
    public static string GetDataMD5(byte[] data)
    {
        StringBuilder sb = new StringBuilder();
        using (MD5 md5 = MD5.Create())
        {
            byte[] newB = md5.ComputeHash(data);
            foreach (byte item in newB)
            {
                sb.Append(item.ToString("x2"));
            }
        }
        return sb.ToString();
    }

    public byte[] Encrypt(byte[] data)
    {
        return RSAEncrypt(data,m_RSAParameters,true);
    }

    public byte[] Decrypt(byte[] data)
    {
        return RSADecrypt(data,m_RSAParameters,true);
    }

    public static void GenNewKey(out string str_Public_Key,out string str_Private_Key)
    {
        RSACryptoServiceProvider RSAalg = new RSACryptoServiceProvider();
        str_Public_Key = Convert.ToBase64String(RSAalg.ExportCspBlob(false));
        GameDebug.Log("生成公钥：" + str_Public_Key);
        str_Private_Key = Convert.ToBase64String(RSAalg.ExportCspBlob(true));
        GameDebug.Log("生成私钥：" + str_Private_Key);
    }
    
    
}